﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Windows.Forms;
using System.Runtime.InteropServices;

namespace SFP.Input
{
    public abstract class Keyboard
    {
        internal static Form form;

        private static Dictionary<Keys, KeyState> keyStates;

        public static KeyboardState GetKeyboardState()
        {
            if (keyStates == null)
            {
                keyStates = new Dictionary<Keys, KeyState>();
                foreach (Keys key in Enum.GetValues(typeof(Keys)))
                {
                    if (!keyStates.ContainsKey(key))
                        keyStates.Add(key, new KeyState(GetKeyState(key), false));
                }
            }
            else
            {
                Dictionary<Keys, KeyState> newKeyStates = new Dictionary<Keys, KeyState>();
                foreach (Keys key in keyStates.Keys)
                {
                    KeyState keyState;
                    keyStates.TryGetValue(key, out keyState);

                    if (keyState == null) keyState = new KeyState(false,false);

                    if (keyState.down)
                    {
                        keyState.down = GetKeyState(key);
                        keyState.pressed = keyState.down;
                    }
                    else{
                        keyState.down = GetKeyState(key);
                    }

                    newKeyStates.Add(key, keyState);
                }

                keyStates = newKeyStates;
            }
            
            return new KeyboardState(keyStates, form);
        }

        [DllImport("user32.dll", CharSet = CharSet.Auto, ExactSpelling = true)]
        private static extern short GetKeyState(int keyCode);

        private static bool GetKeyState(Keys key)
        {
            short retVal = GetKeyState((int)key);

            //If the high-order bit is 1, the key is down. Otherwise, it is up.
            if ((retVal & 0x8000) == 0x8000)
            {
                return true;
            }

            return false;
        }

        internal class KeyState
        {
            internal bool down;
            internal bool pressed;

            public KeyState(bool down, bool pressed)
            {
                this.down = down;
                this.pressed = pressed;
            }
        }
    }
}
